package android.framework.binding;

import java.util.Collection;
import java.util.HashMap;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

public class ItemList<T extends Item> extends ArrayAdapter<T> implements IObserver<Object>, IBindableList<T>{
	private long lastActionId = -1;
	private ListMultiBindingAdapter<T> multiBindingAdapter = new ListMultiBindingAdapter<T>();
	private IViewCreator<T> viewCreator;
	private int resource;
	private HashMap<Integer, MethodRepresent> methodById;
	
	public ItemList(Context context, int resource, IViewCreator<T> viewCreator, HashMap<Integer, MethodRepresent> methodById) {
		this(context, resource, viewCreator);
		this.methodById = methodById;
	}
	public ItemList(Context context, int resource, IViewCreator<T> viewCreator) {
		super(context, resource);
		this.viewCreator = viewCreator;
		this.resource = resource;
	}
	
	public void add(T item){
		item.addListener(this);
		super.add(item);
		lastActionId = Binding.getNextActionId();
		notifyListener(item, ListChangeOperation.Add, lastActionId);
	}
	
	public void remove(T item){
		item.removeListener(item);
		super.remove(item);
		lastActionId = Binding.getNextActionId();
		notifyListener(item, ListChangeOperation.Remove, lastActionId);
	}

	public boolean notifyChanges(Object value, long actionId) {
		notifyDataSetChanged();
		return true;
	}

	public View getView(int position, View convertView, ViewGroup parent){
		View v = convertView;
		if (v == null) {
			LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			v = vi.inflate(resource, null);
		}
		
		if(viewCreator != null){
			T current = getItem(position);
			viewCreator.createView(position, v, parent, current, methodById);
		}
		return v;
	}
	
	
	public boolean onListChanged(T item, ListChangeOperation changeOperation, long actionId) {
		if(actionId > lastActionId){
			this.lastActionId = actionId;
			applyChanges(item, changeOperation, actionId);
			return true;
		}
		return false;
	}
	private void applyChanges(T item, ListChangeOperation changeOperation, long actionId) {
		switch (changeOperation) {
			case Add:
				super.add(item);
				break;
	
			case Remove:
				super.remove(item);
				break;
		}
		notifyListener(item, changeOperation, actionId);
	}
	
	public void addListener(IListObserver<T> listener) {
		multiBindingAdapter.addObserver(listener);
	}
	public void removeListener(IListObserver<T> listener) {
		multiBindingAdapter.removeObserver(listener);
	}
	public void setListener(ListMultiBindingAdapter<T> listener) {
		multiBindingAdapter = listener;
	}

	protected void notifyListener(T item, ListChangeOperation operation){
		lastActionId = Binding.getNextActionId();
		notifyListener(item, operation, lastActionId);
	}
	
	private void notifyListener(T item, ListChangeOperation operation, long actionId){
		if(multiBindingAdapter != null){
			multiBindingAdapter.onListChanged(item, operation, actionId);
		}
	}
	
	public void addAll(Collection<T> collection){
		for (T item : collection) {
			add(item);
		}			
	}

}
